home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_100 / 187_01 / fixpath.c < prev    next >
Text File  |  1986-02-19  |  5KB  |  133 lines

  1. /*@================================================================ */
  2. /*@
  3.   @  From Dr. Dobbs #108 October 1985.   */
  4.  
  5. /*@ fixpath() processes a DOS pathname for two different uses.
  6.   @    The input path, *ip, is presumably a command operand like the 
  7.   @    first operand of DIR.  One output, the search path *sp, is 
  8.   @    the input possibly augmented with "*.*" or "\*.*" so that it 
  9.   @    will work reliably with DOS functions 4E/$f.  The other output
  10.   @    is a lead-in path, *lip, which can be prefixed to the simple 
  11.   @    filename.ext returned by fuctions 4E/4F to make a complete path 
  12.   @    for opening or erasing a file.
  13.   @
  14.   @    The function returns 1 if it is successful, but 0 if the 
  15.   @    input path can't be processed and should not be used.
  16.   @
  17.   @    Some input paths can be processed here yet be invalid or 
  18.   @    useless.  The search path produced from such an input wwill
  19.   @    cause an error return from function 4E (search first match). */
  20. /* ================================================================ */
  21.  
  22. int fixpath(ip, sp, lip)
  23. register char     *ip,    /* input path */
  24.                 *sp,    /* the search path */
  25.                 *lip;    /* the lead-in or prefix path */
  26. {
  27.     char *cp;            /* work pointer for scanning paths */
  28.     int attr;            /* attribute for chgattr */
  29.     int ret, strlen(), strcpy(), strcmp(), strcat(), chgattr();
  30.  
  31. /* ================================================================ */
  32. /*    Pick off 4 special cases:
  33.     (1)    the NULL string, which we take to mean "*.*"
  34.     (2)    the simple "d:" reference to a drive, which we also take
  35.         to mean "d:*.*"
  36.     (3)    the root-dir reference "d:\" which is mishandled by 
  37.         function 0x4300 of both DOS 2.1 and 3.0.
  38.     (4)    any reference that ends in "\"
  39.  
  40.     In all cases, the input path is ok as a lead-in, but it needs
  41.     the global qualifier *.* added for searching.
  42.  
  43. /* ================================================================ */
  44.  
  45.     if ((strlen(ip) == 0)                /* null string */
  46.         || (strcmp(ip+1, ":") == 0)        /* d: only */
  47.         || (ip[strlen(ip)-1] == '\\'))    /* ends in backslash */
  48.         {
  49.             strcpy(lip, ip);            /* input is ok as prefix */
  50.             strcpy(sp, ip);
  51.             strcat(sp, "*.*");            /* add *.* for search */
  52.             return (1);
  53.         }
  54.  
  55. /* ================================================================ */
  56. /*    Ok, we have a non-null string not ending in \ and not a lone
  57.     drive letter.  Four possibilities remain:
  58.     (1)    an explicit file reference, b:\mydir\mydat
  59.     (2)    an explicit directory reference, \mydir
  60.     (3)    an ambiguous file reference, *.* or b:\mydir\*.dat
  61.     (4)    an unknown name, a:noway or b:\mydir\nonesuch.dat
  62.  
  63.     We can separate this with fair reliability using DOS function
  64.     0x4300, get attributes from path.
  65.  
  66.  
  67. /* ================================================================ */
  68.  
  69.     attr = 0x0000;                        /* output area for get command */
  70.     ret = chgattr('G', ip, &attr);        /* get attributes for this path */
  71.  
  72.     if (ret == 0x0002) 
  73.  
  74.     /*   the path is valid, in that all directories and drives
  75.         named in it are valid, but the final name is unknown.  No
  76.         files will be found in a search, so quit now.   */
  77.  
  78.         return (0);
  79.  
  80.     if ((ret == 0x0003) 
  81.         || ((ret == 0) && ((attr & 0x0010) == 0))) {
  82.  
  83.     /* Error 3, path not found, could mean total junk or a 
  84.         misspelt directory name, but most likely it just means
  85.         the path ends in an ambiguous name.  If there's an error
  86.         the initial search (function 4Eh) will fail.
  87.  
  88.         With no error and reg cx not showing the directory 
  89.         attribute flags 0010, we have a normal, unambiguous file
  90.         pathname like "b:\mydir\mydat" or just "myprog.com".
  91.  
  92.         In either case the search path is the whole input
  93.         path.  The lead-in is that shorn of whatever follows the 
  94.         rightmost \ or :, whichever comes last -- or just a null
  95.         string if there is no \ or :.        */
  96.  
  97.         strcpy(sp, ip);            /* working copy of ip in sp */
  98.         cp = sp + strlen(sp) -1;
  99.         for (; cp > sp; --cp)
  100.             if (('\\' == *cp) || (':' == *cp)) 
  101.                 break;
  102.         if (cp > sp)
  103.             ++cp;                /* retain colon or slash */
  104.         *cp = '\0';                /* make a null string */
  105.         strcpy(lip, sp);
  106.         strcpy(sp, ip);            /* whole input for search */
  107.         return (1);
  108.     }
  109.  
  110.     if ((ret == 0) && (attr & 0x0010)) {
  111.  
  112.     /* No error and the directory attribute returned in cx
  113.         shows an unambiguous path that happpens to end in the 
  114.         name of a directory, for instance "..\..\bin" or
  115.         "b:\mydir".  Applying the rules of DIR or COPY, we
  116.         have to treat these as global refs to all files named in 
  117.         the directory.  The search path is the input with 
  118.         "\*.*" tacked onto it.  The lead-in path is just the 
  119.         input plus a backslash.            */
  120.  
  121.         strcpy(sp, ip);
  122.         strcpy(lip, ip);
  123.         strcat(sp, "\\*.*");
  124.         strcat(lip, "\\");
  125.         return (1);
  126.     }
  127.  
  128.     else {
  129.         /* unexpected events make me nervous, so give up */
  130.         return (0);
  131.     }
  132. }
  133.